/**
 * 1. promise 就是一个类，执行的时候会传递一个执行器进去，执行器会立即执行，执行器接收两个参数，resolve reject
 * 2. 三个状态，分别为 成功 fulfilled 失败 rejected 等待中 pending，只能从 pending 更改为 fulfilled 或者 rejected 不能在 fulfilled 和 reject 两者来回切换
 *      pending -> fulfilled      pending -> rejected   状态一旦确认 不可更改
 * 3. resolve 和 reject 是用来更改状态的，resolve 更改为 fulfilled | reject 更改为 rejected
 * 4. then 方法做的是判断当前状态，如果当前状态是成功，则调用成功方法，如果当前状态是失败，则调用失败方法
 * 5. 当调用成功的回调的时候需要把成功之后的值给成功回调，当调用失败的回调的时候需要把失败之后的原因给失败回调
 * 
 * 加入异步代码
 *  setTimeout(() => {
        resolve('成功')
    }, 2000)
 * 解释：代码是从上到下依次执行，这里如果是异步代码的话，代码会先执行到后面的 .then 然后两秒钟之后上面的 resolve 才执行，而执行 .then 的时候，当前状态是 pending(没有执行 resolve或者reject) , 所以如果有异步代码的时候在 .then里面需要将成功回调和失败回调存起来，在两秒之后执行 resolve 或者 reject 的时候再执行 .then 的成功或失败回调
 * 6. then 方法被多次调用的时候，每一个 then 方法都是要被执行的，
 *      同步情况：成功或者失败的回调会直接执行，这里不需要改动，因为现在的逻辑就是这样
 *      异步情况：成功或者失败的时候需要依次调用所有的回调，所以如果是 pending 的状态需要将所有的成功和失败回调都需要存储起来，都存储的话就只能用 array 去存储了
 * 7. then 方法可以链式调用，后面的 then 方法拿到的值是上一个 then 方法的回调函数的返回值
 *      then 方法想要实现链式调用，那么上一个 then 方法应该返回的是一个新得 promise 对象
 *      返回普通值：直接调用 resolve 返回当前结果
 *      返回 promise 对象：查看 promise 对象返回的结果，再根据返回结果去决定是 resolve 还是 reject
 *      因为 这个判断好几处地方都需要使用，所以单独封装成一个方法调用，接收 返回值和返回的当前 promise 的 resolve 和 reject
 *      如果是普通值，直接调用 resolve 
 *      如果是 promise ，根据这个 promise 的状态来决定调用 resolve 还是 reject 
 * 8. 在 then 方法回调函数中可以返回 promise 对象，但是有一种情况不行，就是直接返回当前 then 方法对应的 promise 对象，如果当前的 then 方法回调函数内返回的是当前 then 方法返回的那个 promise 对象，就发生了 promise 对象循环调用的错误，程序是不被允许的
 *      这里需要判断当前返回的 新的 promise 对象和回调函数返回的值，是否相同，如果相同，说明发生了 promise 对象循环调用的错误，直接 return 并调用 reject 就行，
 *      但是当前 then 返回的 promise 在当前 then 的回调函数内部没法使用啊，因为还没生成呢，我们可以用一个异步来解决一下
 * 9. 现在当程序内部发生错误的情况下还没有捕获错误，需要捕获一下
 *      首先是执行器，发生错误的时候需要将当前 promise 切换失败状态
 *      其次要处理 then 方法的回调函数，如果回调函数报错，错误要在下一个 then 方法错误回调中捕获到
 * 10. 只处理了成功的情况，失败的情况按照成功的情况同样处理一下
 *      还有一个情况，如果是异步的时候，存储的时候是将回调直接存储到数组当中的，半路没法去处理，所以这里改一下，成功和失败的回调存储的时候存储一个匿名函数，匿名函数内部直接执行成功或者失败的回调函数，这样我们就可以在匿名函数里面对成功和失败的回调函数进行处理了，并且在半路对成功和失败进行处理的时候，值已经传递过去了，所以在 resolve 和 reject 内部执行成功或失败的回调函数的时候就不需要传递值了
 * 11. then 方法两个参数，原生 promise 的两个参数都是可选参数，而且多次调用 then 方法，值会不断的往下传递，这里只需要给 成功和失败 的回调函数一个默认值就行
 * 12. 原生 promise 有个 all 方法，用来解决异步并发问题。这里同样实现一个 all 方法
 *      接收一个数组，数组的元素什么都行，promise.all 返回的也是一个 promise 对象，可以链式调用，并且如果有一个是失败的，整个 all 都是失败的
 *      但是当中如果有异步操作，这时候在循环之后调用 resolve 的时候异步代码还没执行，所以结果会出现空值
 *      解决办法就是每 addData 依次，记录一下，当记录的次数和 array 数组长度一致的时候，说明异步情况也都执行完了，直接执行 resolve 
 * 13. 原生 promise 有一个 resolve 方法，作用是 将当前的值快速的编程一个 promise 对象，方便链式调用
 *      resolve 接收一个值，内部先判断是否是 promise 对象，如果是，直接原封不动返回，如果不是，则创建一个 promise 对象返回
 * 14. finally 方法，无论是成功还是失败，回调函数始终都会被执行依次，后面还可以链式调用 then 方法拿到结果
 *      finally 回调函数当中还能 return 一个 promise 对象，内部是一个异步调用，在 finally 内部需要等待这个异步调用去执行
 *      需要借助 resolve 这个方法看 callback 返回值是什么，如果返回的是一个普通值，转换成 promise 对象并等待 promise 执行完成，如果返回的是一个 promise 对象，那么就去等待你的 promise 对象执行完成然后返回这个 value 
 * 15. catch 方法，用来处理当前的 promise 对象最终的状态为失败的情况，也就是调用 then 方法的时候不传递失败方法的回调，那么这个失败回调就会被 catch 方法捕获
 *      从而去执行 catch 方法的回调函数
 */

const MyPromise = require('./MyPromise')

// let mypromise = new MyPromise((resolve, reject) => {
//     // throw new Error('执行器错误')
//     setTimeout(() => {
//         // resolve('成功')
//         reject('失败')
//     }, 2000)
//     // reject('失败')
// })

// mypromise.then(value => {
//     console.log(value)
//     // throw new Error('then error')
//     // return 'setTimeout aaa'
//     // return 'setTimeout aaa'
// }, reason => {
//     console.log(reason)
//     // throw new Error('then error111')
//     // return 1000
// })
//     .then(value => {
//         console.log(value)
//     }, reason => {
//         console.log(reason.message)
//     })

// mypromise.then()
//     .then()
//     .then(value=>console.log(value),reason=>console.log(reason))

function p1() {
    return new MyPromise(function (resolve, reject) {
        setTimeout(() => {
            resolve('p1 成功')
        }, 2000)
    })
}
function p2() {
    return new MyPromise(function (resolve, reject) {
        // resolve('p2 成功')
        // reject('reject p2')
    })
}

p1()
    .then(value => console.log(value))
    .catch(reason => console.log(reason))

// p2().finally(()=>{
//     console.log('finally')
//     return p1()
// })
// .then(value=>{
//     console.log(value)
// },reason=>{
//     console.log(reason)
// })

// MyPromise.all(['a','b',p1(),p2(),'c'])
// .then(result=>console.log(result))

// MyPromise.resolve(1000)
//     .then(value => console.log(value))
// MyPromise.resolve(p1())
//     .then(value => console.log(value))